﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;
using HtmlAgilityPack;
using NLog;
using ThePlaceRuMainForm.Models;
using HtmlDocument = HtmlAgilityPack.HtmlDocument;


namespace ThePlaceRuMainForm.Classes
{
    class ThePlaceRuDownloader : Downloader
    {
        private static readonly Logger _logger = LogManager.GetCurrentClassLogger();
        public List<string> CelebritiesFeeds = new List<string>();
        public string DefaultPhotosPath { get; set; }
        const string BaseUrl = "http://www.theplace.ru";
        #region constructors
        public ThePlaceRuDownloader(string name)
            : base(name)
        {

        }
        public ThePlaceRuDownloader(string name, IEnumerable<string> photoFeeds)
            : base(name)
        {
            CelebritiesFeeds.AddRange(photoFeeds);
        }
        #endregion

        public override IEnumerable<Celebrity> GetCelebrities()
        {
            try
            {
                var doc = new HtmlDocument();
                var celebrities = new List<Celebrity>();
                foreach (var celebritiesFeed in CelebritiesFeeds)
                {
                    var nationality = GetNationality(celebritiesFeed);
                    var request = WebRequest.Create(celebritiesFeed) as HttpWebRequest;
                    if (request == null) continue;
                    var response = request.GetResponse();
                    using (var stream = response.GetResponseStream())
                    {
                        doc.Load(stream, Encoding.GetEncoding("windows-1251"));

                        var modelListTable = doc.GetElementbyId("models_list");
                        if (modelListTable == null) continue;
                        var nodeCollection = modelListTable.SelectNodes("tr[1]/td/div[position()>1]/div/a");
                        if (nodeCollection == null) continue;

                        /*Parallel.ForEach(nodeCollection, node =>
                        {
                            var celebrity = new Celebrity();
                            celebrity.Name = node.InnerText;
                            celebrity.Url = DefaultPhotosPath + node.Attributes["href"].Value;
                            celebrity.Nationality = nationality;
                            celebrity.Pages = GetCelebritiesPagesCount(celebrity);
                            _logger.Info("add {0}", celebrity.ToString());
                            celebrities.Add(celebrity);
                            
                        });*/
                        int count = 5;
                        foreach (HtmlNode node in nodeCollection)
                        {
                            var celebrity = new Celebrity();
                            celebrity.Name = node.InnerText;
                            celebrity.Url = DefaultPhotosPath + node.Attributes["href"].Value;
                            celebrity.Nationality = nationality;
                            celebrity.Pages = GetCelebritiesPagesCount(celebrity);
                            _logger.Info("add {0}", celebrity.ToString());
                            celebrities.Add(celebrity);
                            count--;
                            if (count == 0) break;

                        }

                    }
                }

                return celebrities;

            }
            catch (Exception e)
            {
                _logger.ErrorException(e.Message, e);
            }
            return null;
        }

        public int GetCelebritiesPagesCount(Celebrity celebrity)
        {
            var doc = new HtmlDocument();
            var request = WebRequest.Create(celebrity.Url) as HttpWebRequest;
            if (request != null)
            {
                try
                {
                    var response = request.GetResponse();
                    using (var stream = response.GetResponseStream())
                    {
                        doc.Load(stream, Encoding.GetEncoding("windows-1251"));

                        var pagesSelectors = doc.DocumentNode.SelectNodes("//a[@class='page_b_off']");
                        if (pagesSelectors != null)
                        {
                            var lastPage = pagesSelectors.Last();
                            var count = int.Parse(lastPage.InnerText);
                            return count;
                        }
                    }

                }
                catch (WebException e)
                {
                    _logger.ErrorException(e.Message, e);
                    _logger.Error("Celebrity {0} not found url: {1}", celebrity.Name, celebrity.Url);
                    if (((HttpWebResponse)e.Response).StatusCode == HttpStatusCode.NotFound) return -1;
                }

            }
            return 1;
        }

        private National GetNationality(string celebritiesFeed)
        {
            switch (celebritiesFeed)
            {
                case "http://www.theplace.ru/photos/?s_id=0":
                    return National.eng;
                case "http://www.theplace.ru/photos/?s_id=1":
                    return National.rus;
                default:
                    return National.eng;
            }
        }

        public IEnumerable<Photo> GetAllPhotosCelebrity(Celebrity celebrity)
        {

            var pageMax = celebrity.Pages;
            var images = new List<Photo>(100);
            IEnumerable<int> pages = Enumerable.Range(1, pageMax);
            //int count = 1;
            Parallel.ForEach(pages, page =>
            {
                var doc = new HtmlDocument();
                //http://www.theplace.ru/photos/gallery.php?id=2525&page=1
                var url = celebrity.Url + "&page=" + page;
                _logger.Info(string.Format("goto {0}", url));
                var request = WebRequest.Create(url) as HttpWebRequest;
                if (request != null)
                {

                    var response = request.GetResponse();
                    using (var stream = response.GetResponseStream())
                    {
                        doc.Load(stream, Encoding.GetEncoding("windows-1251"));

                        var divsWithImageDirectLink =
                            doc.DocumentNode.SelectNodes("//div[@class='pic_s']");
                        if (divsWithImageDirectLink != null)
                        {
                            foreach (HtmlNode divWithDirectLinkToImage in divsWithImageDirectLink)
                            {
                                var link = divWithDirectLinkToImage.SelectSingleNode("a").Attributes["href"].Value;
                                var directImageUrl = GetDirectImageUrlFromPage(BaseUrl + link);
                                images.Add(new Photo { Link = directImageUrl, Name = GetFileName(directImageUrl, page) });
                                // Interlocked.Increment(ref count);
                            }
                        }
                    }

                }
            });
            return images;
        }

        private string GetFileName(string directImageUrl, int page)
        {
            // http://www.theplace.ru/archive/scarlett_johanssen/img/www_bruce_juice_com_-1127.jpg
            // http://www.theplace.ru/archive/scarlett_johanssen/img/Scarlett_Johansson_-8.jpg
            var name = string.Format("p{0}-{1}", page, GetNameWithExtensionFromLink(directImageUrl));
            return name;
        }
        private string GetNameWithExtensionFromLink(string image)
        {
            Uri uri = new Uri(image);
            return uri.Segments.Last();
        }
        private string GetDirectImageUrlFromPage(string pageWithImage)
        {
            var doc = new HtmlDocument();
            var request = WebRequest.Create(pageWithImage) as HttpWebRequest;
            if (request != null)
            {

                var response = request.GetResponse();
                using (var stream = response.GetResponseStream())
                {
                    doc.Load(stream, Encoding.GetEncoding("windows-1251"));

                    var image =
                        doc.DocumentNode.SelectSingleNode("/html/body/div[3]/img");
                    if (image != null)
                    {
                        var directLink = image.Attributes["src"].Value;
                        if (!string.IsNullOrEmpty(directLink))
                        {
                            return BaseUrl + directLink;
                        }
                    }
                }

            }
            return null;
        }

        public string GetCorrectLink(string inLink)
        {
            var doc = new HtmlDocument();
            var request = WebRequest.Create(inLink) as HttpWebRequest;
            if (request != null)
            {
                try
                {
                    var response = request.GetResponse();
                    using (var stream = response.GetResponseStream())
                    {
                        doc.Load(stream, Encoding.GetEncoding("windows-1251"));

                        var pagesSelectors = doc.DocumentNode.SelectNodes("//a[@class='page_b_off']");
                        if (pagesSelectors != null)
                        {
                            var lastPage = pagesSelectors.Last();
                            var rUri = new Uri(BaseUrl + lastPage.Attributes["href"].Value);
                            var uriString = rUri.ToString();
                            return uriString.Substring(0, uriString.IndexOf('&'));
                        }
                        //one pages only
                        //http://www.theplace.ru/photos/photo.php?id=329990
                        return inLink;
                    }

                }
                catch (WebException e)
                {
                    _logger.ErrorException(e.Message, e);
                }

            }
            return null;
        }

        public int GetCountPhotoCelebrities(Celebrity celebrity)
        {
            var doc = new HtmlDocument();
            var request = WebRequest.Create(celebrity.Url) as HttpWebRequest;
            if (request != null)
            {
                try
                {
                    var response = request.GetResponse();
                    using (var stream = response.GetResponseStream())
                    {
                        doc.Load(stream, Encoding.GetEncoding("windows-1251"));

                        var photoCount = doc.DocumentNode.SelectSingleNode("//td[@class='t10_gray']");
                        if (photoCount != null)
                        {
                            // [фотографий в галерее: 2150]
                            var text = photoCount.InnerText;
                            Regex regex = new Regex(@"\d+");
                            Match match = regex.Match(text);
                            if (match.Success)
                            {
                                return Convert.ToInt32(match.Value);
                            }
                        }

                        return 0;
                    }

                }
                catch (WebException e)
                {
                    _logger.ErrorException(e.Message, e);
                }

            }
            return 0;
        }
    }
}
